/*------------------------------------------------------------------------------
 * Fortress DS
 * 
 * Copyright (c) 2008 David Panseri
 * distributed under the terms of the GNU General Public License
 -------------------------------------------------------------------------------
 *
 * main.cpp
 *
 -----------------------------------------------------------------------------*/
#include <nds.h>
#include <string.h>
#include <nds/arm9/console.h> //basic print funcionality
#include <stdio.h>
#include "Level.h"
#include "OAM.h"
#include "Sprite.h"
#include "TwoFortTiles_bin.h"
#include "TwoFortPal_bin.h"
#include "TwoFortMap_bin.h"

#define MAP_SIZE 1024

#define X_MIN_BOUNDRY 5
#define X_MAX_BOUNDRY 185
#define Y_MIN_BOUNDRY 5
#define Y_MAX_BOUNDRY 120

/*- Function Prototypes-------------------------------------------------------*/
void initVideo(void);
/*----------------------------------------------------------------------------*/

int main(void) 
{
    u16 x=0,y=0;
    int angle=384;
    Level *mTwoFort = new Level((u16)128, (u16)64, (u8*)TwoFortTiles_bin, (u16)TwoFortTiles_bin_size, (u8*)TwoFortPal_bin, (u16)TwoFortPal_bin_size, (u16*)TwoFortMap_bin, (u16)TwoFortMap_bin_size);
    SpriteEntry *pSprite = new SpriteEntry;
    oam Oam;
    Sprite *pCSprite = new Sprite(Oam.getSprite(1));
    tOAM* pCopy;
    
    //initalize video
    initVideo();   
    
    printf("Init OAM\n");
    Oam.initOAM();
    pCopy = Oam.getCopy();
    // Copying the tiles to tile base 1
    printf("Loading tiles!\n");
    mTwoFort->copyTiles((void*)BG_TILE_RAM(1));
    //mTwoFort->copyTiles((void*)BG_TILE_RAM_SUB(1));
    
    // Copying the palette to the palette area
    printf("Loading palette!\n");
    mTwoFort->copyPalette((void*)BG_PALETTE);
    //mTwoFort->copyPalette((void*)BG_PALETTE_SUB);
    //set pallet color for console text
    BG_PALETTE_SUB[255] = RGB15(31,0,0);   
    
    //Copying the map data
    printf("Copying map data!\n");
    mTwoFort->copyMap((void*)BG_MAP_RAM(0),x,y);
    //mTwoFort->copyMap((void*)BG_MAP_RAM_SUB(0),x,y,0,SCR_HEIGHT);

    printf("Set up dummy sprite\n");    
    //pSprite->attribute[0] = ATTR0_COLOR_256 | ATTR0_ROTSCALE_DOUBLE;
    //pSprite->attribute[1] = ATTR1_SIZE_32; // size 64x64, x 10
    //pSprite->attribute[2] = 64;
    pCSprite->setAttributes((u16)ATTR0_COLOR_256 | ATTR0_ROTSCALE_DOUBLE,
                            (u16)ATTR1_SIZE_32,
                            (u16)64);
    //pSprite->posX = 95;
    //pSprite->posY = 60;
    pCSprite->setPosition(95,60);
    
    // Blue for 256 color sprite
    SPRITE_PALETTE[1]=RGB15(31,0,0);
    SPRITE_PALETTE[2]=RGB15(0,0,31);

    // blue 64*64 square for 256 color mode (must write two pixles at time)
    for(int i=0;i<32*16;i++)
    {
            SPRITE_GFX[i+64*16]=(1<<8)|1;
    }
    pCopy->matrixBuffer[0].hdx=256;
    pCopy->matrixBuffer[0].hdy=0;
    pCopy->matrixBuffer[0].vdx=0;
    pCopy->matrixBuffer[0].vdy=256;
                
    //Oam.setSprite(1,pSprite);
    //main loop
    printf("Entering main loop!\n");
    while(TRUE)
    {
	pCopy->matrixBuffer[0].hdx = COS[angle & 0x1FF] >> 4;
	pCopy->matrixBuffer[0].hdy = SIN[angle & 0x1FF] >> 4;
	pCopy->matrixBuffer[0].vdx = -pCopy->matrixBuffer[0].hdy;
	pCopy->matrixBuffer[0].vdy = pCopy->matrixBuffer[0].hdx;
        
        swiWaitForVBlank();
        Oam.updateOAM();
        
        // read the button states
	scanKeys();
        
        if ( keysHeld() & KEY_UP)
        {
            pCopy->spriteBuffer[1].posY += pCopy->matrixBuffer[0].hdy/100;
            
            if(pCopy->spriteBuffer[1].posY < Y_MIN_BOUNDRY)
            {
                pCopy->spriteBuffer[1].posY = Y_MIN_BOUNDRY;
                
                if(y <= 0)
                    y = 0;
                else
                    y--;
            }
            
            if(pCopy->spriteBuffer[1].posY > Y_MAX_BOUNDRY)
            {
                pCopy->spriteBuffer[1].posY = Y_MAX_BOUNDRY;
                
                if(y > mTwoFort->getHeight()-24)
                    y = mTwoFort->getHeight() - 24;
                else
                    y++;
            }
            
            pCopy->spriteBuffer[1].posX += pCopy->matrixBuffer[0].hdx/100; 
            
            if(pCopy->spriteBuffer[1].posX < X_MIN_BOUNDRY)
            {
                pCopy->spriteBuffer[1].posX = X_MIN_BOUNDRY;
                
                if(x <= 0)
                    x = 0;
                else
                    x--;
            }
            
            if(pCopy->spriteBuffer[1].posX > X_MAX_BOUNDRY)
            {
                pCopy->spriteBuffer[1].posX = X_MAX_BOUNDRY;
                
                if(x > mTwoFort->getWidth()-24)
                    x = mTwoFort->getWidth() - 24;
                else
                    x++;
            }
            printf("PosX = %d (%d) PosY = %d (%d)\n",pCopy->spriteBuffer[1].posX,x,pCopy->spriteBuffer[1].posY,y);
        }

        if ( keysHeld() & KEY_DOWN)
        {
            pCopy->spriteBuffer[1].posY -= pCopy->matrixBuffer[0].hdy/100;//y-=1;
            
            if(pCopy->spriteBuffer[1].posY < Y_MIN_BOUNDRY)
                pCopy->spriteBuffer[1].posY = Y_MIN_BOUNDRY;
            
            if(pCopy->spriteBuffer[1].posY > Y_MAX_BOUNDRY)
                pCopy->spriteBuffer[1].posY = Y_MAX_BOUNDRY;
            
            pCopy->spriteBuffer[1].posX -= pCopy->matrixBuffer[0].hdx/100;
            
            if(pCopy->spriteBuffer[1].posX < X_MIN_BOUNDRY)
                pCopy->spriteBuffer[1].posX = X_MIN_BOUNDRY;
            
            if(pCopy->spriteBuffer[1].posX > X_MAX_BOUNDRY)
                pCopy->spriteBuffer[1].posX = X_MAX_BOUNDRY;
            
        }
        
        if ( keysHeld() & KEY_LEFT)
            angle-=5;

        
        if ( keysHeld() & KEY_RIGHT)
            angle+=5;
        
        mTwoFort->copyMap((void*)BG_MAP_RAM(0),x,y);
        //mTwoFort->copyMap((void*)BG_MAP_RAM_SUB(0),x,y,0,SCR_HEIGHT);

    }
    return( 0 );
}

void initVideo(void)
{
    //set mode 0 and activate BG0 for main BG
    videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D);
    //set mode 0 and activate BG0 for sub BG
    videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG1_ACTIVE);
    
    //set VRAM bank A as main BG 
    //set VRAM bank B for main BG
    //set up VRAM bank C for sub BG
    //do nothing with VRAM bank D
    vramSetMainBanks(VRAM_A_MAIN_BG_0x06000000,
                     VRAM_B_MAIN_SPRITE_0x06400000,
                     VRAM_C_SUB_BG_0x06200000,
                     VRAM_D_LCD);
    
    //set main background 0 as 32x32 tiled, 256 color, and use map base 0 and tile base 1
    BG0_CR = BG_32x32 | BG_COLOR_256 | BG_MAP_BASE(0) | BG_TILE_BASE(1);
    
    //set sub background 0 as 32x32 tiled, 256 color, and use map base 0 and tile base 1
    SUB_BG1_CR = BG_32x32 | BG_COLOR_256 | BG_MAP_BASE(0) | BG_TILE_BASE(1) | BG_PRIORITY(1);
    
    // set up sub background 1 for text
    SUB_BG0_CR = BG_MAP_BASE(31) | BG_PRIORITY(0) | BG_TILE_BASE(2);
    BG_PALETTE_SUB[255] = RGB15(31,0,0);//by default font will be rendered with color 255
    
    //init console
    consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(2), 16);
    
    //set up vblank interrupt
    irqInit();
    irqEnable(IRQ_VBLANK);
}